
Imports System.Net.Sockets
Imports System.IO
Imports System.Threading

Public MustInherit Class udpHandle
    Protected Friend stream As udpstream = Nothing
    Public reader As StreamReader = Nothing
    Public writer As StreamWriter = Nothing

    Protected Friend MustOverride Function localport() As Int32
    Protected Friend MustOverride Function remoteport() As Int32
    Protected Friend MustOverride Function remoteaddress() As String

    Protected Sub initial(ByVal localport As Int32, ByVal remoteaddress As String, ByVal remoteport As Int32)
        On Error Resume Next

        stream = New udpstream(localport, remoteaddress, remoteport)
        assert(Not stream Is Nothing, "failed to create new instance of stream")
        reader = New StreamReader(stream, encoding.utf8, False)
        writer = New StreamWriter(stream)
        writer.AutoFlush = True
        assert(Not reader Is Nothing AndAlso Not writer Is Nothing, "failed to create new instance of reader or writer")
    End Sub

    Public Sub New()
        initial(localport(), remoteaddress(), remoteport())
    End Sub

    Public Sub New(ByVal localport As Int32, ByVal remoteaddress As String, ByVal remoteport As Int32)
        initial(localport, remoteaddress, remoteport)
    End Sub

    Protected Overrides Sub Finalize()
        On Error Resume Next
        closestream(writer)
        closestream(reader)
        closestream(stream)

        MyBase.Finalize()
    End Sub
End Class

Public Class udpHandleUnittest
    Inherits udpHandle

    Protected Friend Overrides Function localport() As Integer
        Return npos
    End Function

    Protected Friend Overrides Function remoteaddress() As String
        Return Nothing
    End Function

    Protected Friend Overrides Function remoteport() As Integer
        Return npos
    End Function

    Public Sub New(ByVal localport As Int32, ByVal remoteaddress As String, ByVal remoteport As Int32)
        MyBase.New(localport, remoteaddress, remoteport)
    End Sub

    Protected Shared handle As udpHandleUnittest = Nothing

    Protected Shared Sub read()
        Dim s As String = Nothing
        s = handle.reader.ReadLine()
        While True
            Console.WriteLine(s)
            s = handle.reader.ReadLine()
        End While
    End Sub

    Public Shared Sub unittest()
        Dim localport As Int32
        Dim remoteaddress As String
        Dim remoteport As Int32
retrySrcPort:
        Console.WriteLine("input source / local port")
        If Not convertor.toint32(Console.ReadLine(), localport) Then
            GoTo retrySrcPort
        End If
        Console.WriteLine("input destination address")
        remoteaddress = Console.ReadLine()
retryDestPort:
        Console.WriteLine("input destination port")
        If Not convertor.toint32(Console.ReadLine(), remoteport) Then
            GoTo retryDestPort
        End If

        handle = New udpHandleUnittest(localport, remoteaddress, remoteport)
        Dim readthread As Thread = Nothing
        readthread = New Thread(AddressOf read)
        readthread.Start()

        Dim input As String
        input = Console.ReadLine()
        While Not input Is Nothing
            handle.writer.WriteLine(input)
            input = Console.ReadLine()
        End While
    End Sub
End Class